/**
 * @class UserSessionLog 用户会话日志模型
 */
const BaseMod = require('./base');
const Platform = require('./platform');
const Channel = require('./channel');
const { DateTime } = require('../lib');
module.exports = class UserSessionLog extends BaseMod {
    constructor() {
        super();
        this.tableName = 'user-session-logs';
    }

    /**
     * 用户会话日志数据填充
     * @param {Object} params 上报参数
     */
    async fill(params) {
        if (!params.sid) {
            return {
                code: 200,
                msg: 'Not found session log',
            };
        }

        if (!params.uid) {
            return {
                code: 200,
                msg: 'Parameter "uid" not found',
            };
        }

        const dateTime = new DateTime();
        const platform = new Platform();
        const channel = new Channel();

        //获取当前页面信息
        if (!params.page_id) {
            const pageInfo = await page.getPageAndCreate(params.ak, params.url, params.ttpj);
            if (!pageInfo || pageInfo.length === 0) {
                return {
                    code: 300,
                    msg: 'Not found this entry page',
                };
            }
            params.page_id = pageInfo._id;
        }

        const nowTime = dateTime.getTime();

        const fillParams = {
            appid: params.ak,
            version: params.v ? params.v : '',
            platform: platform.getPlatformCode(params.ut, params.p),
            channel: channel.getChannelCode(params),
            session_id: params.sid,
            uid: params.uid,
            last_visit_time: nowTime,
            entry_page_id: params.page_id,
            exit_page_id: params.page_id,
            page_count: 0,
            event_count: 0,
            duration: 1,
            is_finish: 0,
            create_time: nowTime,
        };

        const res = await this.insert(this.tableName, fillParams);

        if (res && res.id) {
            return {
                code: 0,
                msg: 'success',
            };
        } else {
            return {
                code: 500,
                msg: 'User session log filled error',
            };
        }
    }

    /**
     * 检测用户会话是否有变化，并更新
     * @param {Object} params 校验参数 - sid:基础会话编号 uid:用户编号 last_visit_user_id:基础会话中最近一个访问用户的编号
     */
    async checkUserSession(params) {
        if (!params.sid) {
            return {
                code: 200,
                msg: 'Not found session log',
            };
        }

        if (!params.uid) {
            //用户已退出会话
            if (params.last_visit_user_id) {
                if (this.debug) {
                    console.log('user "' + params.last_visit_user_id + '" is exit session :', params.sid);
                }
                await this.closeUserSession(params.sid);
            }
        } else {
            //添加用户日志
            if (!params.last_visit_user_id) {
                await this.fill(params);
            }
            //用户已切换
            else if (params.uid != params.last_visit_user_id) {
                if (this.debug) {
                    console.log(
                        'user "' + params.last_visit_user_id + '" change to "' + params.uid + '" in the session :',
                        params.sid
                    );
                }
                //关闭原会话生成新用户对话
                await this.closeUserSession(params.sid);
                await this.fill(params);
            }
        }
        return {
            code: 0,
            msg: 'success',
        };
    }

    /**
     * 关闭用户会话
     * @param {String} sid 基础会话编号
     */
    async closeUserSession(sid) {
        if (this.debug) {
            console.log('close user session log by sid:', sid);
        }
        return await this.update(
            this.tableName,
            {
                is_finish: 1,
            },
            {
                session_id: sid,
                is_finish: 0,
            }
        );
    }

    /**
     * 更新会话信息
     * @param {String} sid 基础会话编号
     * @param {Object} data 更新数据
     */
    async updateUserSession(sid, data) {
        const userSession = await this.getCollection(this.tableName)
            .where({
                session_id: sid,
                uid: data.uid,
                is_finish: 0,
            })
            .orderBy('create_time', 'desc')
            .limit(1)
            .get();

        if (userSession.data.length === 0) {
            console.log('Not found the user session', {
                session_id: sid,
                uid: data.uid,
                is_finish: 0,
            });
            return {
                code: 300,
                msg: 'Not found the user session',
            };
        }

        let nowTime = data.nowTime ? data.nowTime : new DateTime().getTime();
        const accessTime = nowTime - userSession.data[0].createTime;
        const accessSenconds = accessTime > 1000 ? parseInt(accessTime / 1000) : 1;

        const updateData = {
            last_visit_time: nowTime,
            duration: accessSenconds,
        };

        //访问页面数量
        if (data.addPageCount) {
            updateData.page_count = userSession.data[0].page_count + data.addPageCount;
        }
        //最终访问的页面编号
        if (data.pageId) {
            updateData.exit_page_id = data.pageId;
        }
        //产生事件次数
        if (data.eventCount) {
            updateData.event_count = userSession.data[0].event_count + data.addEventCount;
        }

        if (this.debug) {
            console.log('update user session log by sid-' + sid, updateData);
        }

        await this.update(this.tableName, updateData, {
            _id: userSession.data[0]._id,
        });

        return {
            code: 0,
            msg: 'success',
        };
    }

    /**
     * 清理用户会话日志数据
     * @param {Object} days 保留天数, 留存统计需要计算30天后留存率，因此至少应保留31天的日志数据
     */
    async clean(days = 31) {
        days = Math.max(parseInt(days), 1);
        console.log('clean user session logs - day:', days);

        const dateTime = new DateTime();
        const res = await this.delete(this.tableName, {
            create_time: {
                $lt: dateTime.getTimeBySetDays(0 - days),
            },
        });

        if (!res.code) {
            console.log('clean user session log:', res);
        }
        return res;
    }
};
